#include <stdio.h>

/*
 * const修饰的全局变量和局部变量都分配在静态区的“只读数据段”中。
 * const与指针混合使用时，const与类型符前后顺序颠倒后语义不变，
 * 但const与*前后颠倒后语义就变了，一个诀窍是，把类型符去掉，再看const修饰的是变量还是*就可以了。
 * */

int G = 100;

// const修饰参数
int func022(const int p) {
    // p = 1; // Cannot assign to variable 'p' with const-qualified type 'const int'
    return p + 1;
}

// const修饰返回值，一般返回指针，具体指的是修饰*，指针指向的内容不可变
const int * func0221(int p) {
    return &G;
}

int main() {
    const int I = 5;
    int const J = 1; // const放在类型符int的前后都一样

    // const数组，每个元素都是只读的
    const int arr[5] = {3,6,8,10,1};
    int const arr1[5];
    // arr1[2] = 6; // Cannot assign to variable 'arr1' with const-qualified type 'const int [5]'

    int a = arr[0];
    int b = arr1[1];
    printf("&arr:%x\n", &arr); // 61fefc
    printf("&arr[0]:%x\n", &arr[0]); // 61fefc
    printf("&arr==&arr[0]:%x\n", &arr == &arr[0]); //1  数组地址和数组首元素地址是相等的

    // const修饰指针
    // p1可变，p1指向的内存不可变
    const int * p1 = &I; // 等价于 int const * p1 = &I;
    p1 = &J;
    // *p1 = 2; // Read-only variable is not assignable
    // p2不可变，p2指向的内存可变
    int * const p2 = &I;
    // p2 = &J; // Cannot assign to variable 'p2' with const-qualified type 'int *const'
    *p2 = 3;
    // p3不可变，p3指向的内存也不可变
    const int * const p3 = &I;
    // p3 = &J; // Cannot assign to variable 'p3' with const-qualified type 'const int *const'
    // *p3 = 3; // Read-only variable is not assignable

    // 调用const返回值函数
    int *c = func0221(2);
    *c = 90;
    printf("*c:%d\n", *c); // 90
    c = &I;


    return 0;
}
